#include <string.h>
+struct _GskVulkanUploader
+{
+ GdkVulkanContext *vulkan;
+
+ GskVulkanCommandPool *command_pool;
+
+ GSList *staging_image_free_list;
+ GSList *staging_buffer_free_list;
+};
+
struct _GskVulkanImage
{
GObject parent_instance;
G_DEFINE_TYPE (GskVulkanImage, gsk_vulkan_image, G_TYPE_OBJECT)
+GskVulkanUploader *
+gsk_vulkan_uploader_new (GdkVulkanContext *context,
+ GskVulkanCommandPool *command_pool)
+{
+ GskVulkanUploader *self;
+
+ self = g_slice_new0 (GskVulkanUploader);
+
+ self->vulkan = g_object_ref (context);
+ self->command_pool = command_pool;
+
+ return self;
+}
+
+void
+gsk_vulkan_uploader_free (GskVulkanUploader *self)
+{
+ gsk_vulkan_uploader_reset (self);
+
+ g_object_unref (self->vulkan);
+
+ g_slice_free (GskVulkanUploader, self);
+}
+
+void
+gsk_vulkan_uploader_reset (GskVulkanUploader *self)
+{
+ g_slist_free_full (self->staging_image_free_list, g_object_unref);
+ self->staging_image_free_list = NULL;
+ g_slist_free_full (self->staging_buffer_free_list, (GDestroyNotify) gsk_vulkan_buffer_free);
+ self->staging_buffer_free_list = NULL;
+}
+
static GskVulkanImage *
gsk_vulkan_image_new (GdkVulkanContext *context,
gsize width,
}
GskVulkanImage *
-gsk_vulkan_image_new_from_data_via_staging_buffer (GdkVulkanContext *context,
- GskVulkanCommandPool *command_pool,
- guchar *data,
- gsize width,
- gsize height,
- gsize stride)
+gsk_vulkan_image_new_from_data_via_staging_buffer (GskVulkanUploader *uploader,
+ guchar *data,
+ gsize width,
+ gsize height,
+ gsize stride)
{
GskVulkanImage *self;
GskVulkanBuffer *staging;
VkCommandBuffer command_buffer;
guchar *mem;
- staging = gsk_vulkan_buffer_new_staging (context, width * height * 4);
+ staging = gsk_vulkan_buffer_new_staging (uploader->vulkan, width * height * 4);
mem = gsk_vulkan_buffer_map (staging);
if (stride == width * 4)
gsk_vulkan_buffer_unmap (staging);
- self = gsk_vulkan_image_new (context,
+ self = gsk_vulkan_image_new (uploader->vulkan,
width,
height,
VK_IMAGE_TILING_OPTIMAL,
VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
- command_buffer = gsk_vulkan_command_pool_get_buffer (command_pool);
+ command_buffer = gsk_vulkan_command_pool_get_buffer (uploader->command_pool);
vkCmdPipelineBarrier (command_buffer,
VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
}
});
- gsk_vulkan_command_pool_submit_buffer (command_pool, command_buffer, VK_NULL_HANDLE);
+ gsk_vulkan_command_pool_submit_buffer (uploader->command_pool, command_buffer, VK_NULL_HANDLE);
- /* XXX: Is this okay or do we need to keep the staging image around until the commands execute */
- gsk_vulkan_buffer_free (staging);
+ uploader->staging_buffer_free_list = g_slist_prepend (uploader->staging_buffer_free_list, staging);
gsk_vulkan_image_ensure_view (self, VK_FORMAT_B8G8R8A8_SRGB);
}
GskVulkanImage *
-gsk_vulkan_image_new_from_data_via_staging_image (GdkVulkanContext *context,
- GskVulkanCommandPool *command_pool,
- guchar *data,
- gsize width,
- gsize height,
- gsize stride)
+gsk_vulkan_image_new_from_data_via_staging_image (GskVulkanUploader *uploader,
+ guchar *data,
+ gsize width,
+ gsize height,
+ gsize stride)
{
GskVulkanImage *self, *staging;
VkCommandBuffer command_buffer;
- staging = gsk_vulkan_image_new (context,
+ staging = gsk_vulkan_image_new (uploader->vulkan,
width,
height,
VK_IMAGE_TILING_LINEAR,
gsk_vulkan_image_upload_data (staging, data, width, height, stride);
- self = gsk_vulkan_image_new (context,
+ self = gsk_vulkan_image_new (uploader->vulkan,
width,
height,
VK_IMAGE_TILING_OPTIMAL,
VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
- command_buffer = gsk_vulkan_command_pool_get_buffer (command_pool);
+ command_buffer = gsk_vulkan_command_pool_get_buffer (uploader->command_pool);
vkCmdPipelineBarrier (command_buffer,
VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
}
});
- gsk_vulkan_command_pool_submit_buffer (command_pool, command_buffer, VK_NULL_HANDLE);
+ gsk_vulkan_command_pool_submit_buffer (uploader->command_pool, command_buffer, VK_NULL_HANDLE);
- /* XXX: Is this okay or do we need to keep the staging image around until the commands execute */
- g_object_unref (staging);
+ uploader->staging_image_free_list = g_slist_prepend (uploader->staging_image_free_list, staging);
gsk_vulkan_image_ensure_view (self, VK_FORMAT_B8G8R8A8_SRGB);
}
GskVulkanImage *
-gsk_vulkan_image_new_from_data_directly (GdkVulkanContext *context,
- GskVulkanCommandPool *command_pool,
- guchar *data,
- gsize width,
- gsize height,
- gsize stride)
+gsk_vulkan_image_new_from_data_directly (GskVulkanUploader *uploader,
+ guchar *data,
+ gsize width,
+ gsize height,
+ gsize stride)
{
VkCommandBuffer command_buffer;
GskVulkanImage *self;
- command_buffer = gsk_vulkan_command_pool_get_buffer (command_pool);
+ command_buffer = gsk_vulkan_command_pool_get_buffer (uploader->command_pool);
- self = gsk_vulkan_image_new (context,
+ self = gsk_vulkan_image_new (uploader->vulkan,
width,
height,
VK_IMAGE_TILING_LINEAR,
}
});
- gsk_vulkan_command_pool_submit_buffer (command_pool, command_buffer, VK_NULL_HANDLE);
+ gsk_vulkan_command_pool_submit_buffer (uploader->command_pool, command_buffer, VK_NULL_HANDLE);
gsk_vulkan_image_ensure_view (self, VK_FORMAT_B8G8R8A8_SRGB);
}
GskVulkanImage *
-gsk_vulkan_image_new_from_data (GdkVulkanContext *context,
- GskVulkanCommandPool *command_pool,
- guchar *data,
- gsize width,
- gsize height,
- gsize stride)
+gsk_vulkan_image_new_from_data (GskVulkanUploader *uploader,
+ guchar *data,
+ gsize width,
+ gsize height,
+ gsize stride)
{
if (GSK_RENDER_MODE_CHECK (STAGING_BUFFER))
- return gsk_vulkan_image_new_from_data_via_staging_buffer (context, command_pool, data, width, height, stride);
+ return gsk_vulkan_image_new_from_data_via_staging_buffer (uploader, data, width, height, stride);
if (GSK_RENDER_MODE_CHECK (STAGING_IMAGE))
- return gsk_vulkan_image_new_from_data_via_staging_image (context, command_pool, data, width, height, stride);
+ return gsk_vulkan_image_new_from_data_via_staging_image (uploader, data, width, height, stride);
else
- return gsk_vulkan_image_new_from_data_directly (context, command_pool, data, width, height, stride);
+ return gsk_vulkan_image_new_from_data_directly (uploader, data, width, height, stride);
}
GskVulkanImage *
gsk_vulkan_render_pass_upload_fallback (GskVulkanRenderPass *self,
GskVulkanOpRender *op,
GskVulkanRender *render,
- GskVulkanCommandPool *command_pool)
+ GskVulkanUploader *uploader)
{
graphene_rect_t bounds;
cairo_surface_t *surface;
cairo_destroy (cr);
- op->source = gsk_vulkan_image_new_from_data (self->vulkan,
- command_pool,
+ op->source = gsk_vulkan_image_new_from_data (uploader,
cairo_image_surface_get_data (surface),
cairo_image_surface_get_width (surface),
cairo_image_surface_get_height (surface),
void
gsk_vulkan_render_pass_upload (GskVulkanRenderPass *self,
GskVulkanRender *render,
- GskVulkanCommandPool *command_pool)
+ GskVulkanUploader *uploader)
{
GskVulkanOp *op;
guint i;
switch (op->type)
{
case GSK_VULKAN_OP_FALLBACK:
- gsk_vulkan_render_pass_upload_fallback (self, &op->render, render, command_pool);
+ gsk_vulkan_render_pass_upload_fallback (self, &op->render, render, uploader);
break;
case GSK_VULKAN_OP_SURFACE:
{
cairo_surface_t *surface = gsk_cairo_node_get_surface (op->render.node);
- op->render.source = gsk_vulkan_image_new_from_data (self->vulkan,
- command_pool,
+ op->render.source = gsk_vulkan_image_new_from_data (uploader,
cairo_image_surface_get_data (surface),
cairo_image_surface_get_width (surface),
cairo_image_surface_get_height (surface),
{
op->render.source = gsk_vulkan_renderer_ref_texture_image (GSK_VULKAN_RENDERER (gsk_vulkan_render_get_renderer (render)),
gsk_texture_node_get_texture (op->render.node),
- command_pool);
+ uploader);
gsk_vulkan_render_add_cleanup_image (render, op->render.source);
}
break;